/* Copyright 2025 NVIDIA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef __CUPYNUMERIC_C_H__
#define __CUPYNUMERIC_C_H__

// Match these to CuPyNumericOpCode in config.py
// Also, sort these alphabetically except the first one for easy lookup later
enum CuPyNumericOpCode {
  _CUPYNUMERIC_OP_CODE_BASE = 0,
  CUPYNUMERIC_ADVANCED_INDEXING,
  CUPYNUMERIC_ARANGE,
  CUPYNUMERIC_ARGWHERE,
  CUPYNUMERIC_BATCHED_CHOLESKY,
  CUPYNUMERIC_BINARY_OP,
  CUPYNUMERIC_BINARY_RED,
  CUPYNUMERIC_BINCOUNT,
  CUPYNUMERIC_BITGENERATOR,
  CUPYNUMERIC_CHOOSE,
  CUPYNUMERIC_CONTRACT,
  CUPYNUMERIC_CONVERT,
  CUPYNUMERIC_CONVOLVE,
  CUPYNUMERIC_SCAN_GLOBAL,
  CUPYNUMERIC_SCAN_LOCAL,
  CUPYNUMERIC_DIAG,
  CUPYNUMERIC_DOT,
  CUPYNUMERIC_EYE,
  CUPYNUMERIC_FFT,
  CUPYNUMERIC_FILL,
  CUPYNUMERIC_FLIP,
  CUPYNUMERIC_GEEV,
  CUPYNUMERIC_GEMM,
  CUPYNUMERIC_HISTOGRAM,
  CUPYNUMERIC_HISTOGRAMDD,
  CUPYNUMERIC_IN1D,
  CUPYNUMERIC_LOAD_CUDALIBS,
  CUPYNUMERIC_MATMUL,
  CUPYNUMERIC_MATVECMUL,
  CUPYNUMERIC_MP_POTRF,
  CUPYNUMERIC_MP_QR,
  CUPYNUMERIC_MP_SOLVE,
  CUPYNUMERIC_NONZERO,
  CUPYNUMERIC_PACKBITS,
  CUPYNUMERIC_PAD,
  CUPYNUMERIC_POTRF,
  CUPYNUMERIC_PUTMASK,
  CUPYNUMERIC_QR,
  CUPYNUMERIC_RAND,
  CUPYNUMERIC_READ,
  CUPYNUMERIC_REPEAT,
  CUPYNUMERIC_SCALAR_UNARY_RED,
  CUPYNUMERIC_SEARCHSORTED,
  CUPYNUMERIC_SELECT,
  CUPYNUMERIC_SOLVE,
  CUPYNUMERIC_SORT,
  CUPYNUMERIC_SVD,
  CUPYNUMERIC_SYEV,
  CUPYNUMERIC_SYRK,
  CUPYNUMERIC_TAKE,
  CUPYNUMERIC_TILE,
  CUPYNUMERIC_TRANSPOSE_COPY_2D,
  CUPYNUMERIC_TRILU,
  CUPYNUMERIC_TRSM,
  CUPYNUMERIC_UNARY_OP,
  CUPYNUMERIC_UNARY_RED,
  CUPYNUMERIC_UNIQUE,
  CUPYNUMERIC_UNIQUE_REDUCE,
  CUPYNUMERIC_UNLOAD_CUDALIBS,
  CUPYNUMERIC_UNPACKBITS,
  CUPYNUMERIC_WHERE,
  CUPYNUMERIC_WINDOW,
  CUPYNUMERIC_WRAP,
  CUPYNUMERIC_WRITE,
  CUPYNUMERIC_ZIP,
};

// Match these to UnaryOpCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericUnaryOpCode {
  CUPYNUMERIC_UOP_ABSOLUTE = 1,
  CUPYNUMERIC_UOP_ANGLE,
  CUPYNUMERIC_UOP_ARCCOS,
  CUPYNUMERIC_UOP_ARCCOSH,
  CUPYNUMERIC_UOP_ARCSIN,
  CUPYNUMERIC_UOP_ARCSINH,
  CUPYNUMERIC_UOP_ARCTAN,
  CUPYNUMERIC_UOP_ARCTANH,
  CUPYNUMERIC_UOP_CBRT,
  CUPYNUMERIC_UOP_CEIL,
  CUPYNUMERIC_UOP_CLIP,
  CUPYNUMERIC_UOP_CONJ,
  CUPYNUMERIC_UOP_COPY,
  CUPYNUMERIC_UOP_COS,
  CUPYNUMERIC_UOP_COSH,
  CUPYNUMERIC_UOP_DEG2RAD,
  CUPYNUMERIC_UOP_EXP,
  CUPYNUMERIC_UOP_EXP2,
  CUPYNUMERIC_UOP_EXPM1,
  CUPYNUMERIC_UOP_FLOOR,
  CUPYNUMERIC_UOP_FREXP,
  CUPYNUMERIC_UOP_GETARG,
  CUPYNUMERIC_UOP_IMAG,
  CUPYNUMERIC_UOP_INVERT,
  CUPYNUMERIC_UOP_ISFINITE,
  CUPYNUMERIC_UOP_ISINF,
  CUPYNUMERIC_UOP_ISNAN,
  CUPYNUMERIC_UOP_LOG,
  CUPYNUMERIC_UOP_LOG10,
  CUPYNUMERIC_UOP_LOG1P,
  CUPYNUMERIC_UOP_LOG2,
  CUPYNUMERIC_UOP_LOGICAL_NOT,
  CUPYNUMERIC_UOP_MODF,
  CUPYNUMERIC_UOP_NEGATIVE,
  CUPYNUMERIC_UOP_POSITIVE,
  CUPYNUMERIC_UOP_RAD2DEG,
  CUPYNUMERIC_UOP_REAL,
  CUPYNUMERIC_UOP_RECIPROCAL,
  CUPYNUMERIC_UOP_RINT,
  CUPYNUMERIC_UOP_ROUND,
  CUPYNUMERIC_UOP_SIGN,
  CUPYNUMERIC_UOP_SIGNBIT,
  CUPYNUMERIC_UOP_SIN,
  CUPYNUMERIC_UOP_SINH,
  CUPYNUMERIC_UOP_SQRT,
  CUPYNUMERIC_UOP_SQUARE,
  CUPYNUMERIC_UOP_TAN,
  CUPYNUMERIC_UOP_TANH,
  CUPYNUMERIC_UOP_TRUNC,
};

// Match these to UnaryRedCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericUnaryRedCode {
  CUPYNUMERIC_RED_ALL = 1,
  CUPYNUMERIC_RED_ANY,
  CUPYNUMERIC_RED_ARGMAX,
  CUPYNUMERIC_RED_ARGMIN,
  CUPYNUMERIC_RED_CONTAINS,
  CUPYNUMERIC_RED_COUNT_NONZERO,
  CUPYNUMERIC_RED_MAX,
  CUPYNUMERIC_RED_MIN,
  CUPYNUMERIC_RED_NANARGMAX,
  CUPYNUMERIC_RED_NANARGMIN,
  CUPYNUMERIC_RED_NANMAX,
  CUPYNUMERIC_RED_NANMIN,
  CUPYNUMERIC_RED_NANPROD,
  CUPYNUMERIC_RED_NANSUM,
  CUPYNUMERIC_RED_PROD,
  CUPYNUMERIC_RED_SUM,
  CUPYNUMERIC_RED_SUM_SQUARES,
  CUPYNUMERIC_RED_VARIANCE
};

// Match these to BinaryOpCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericBinaryOpCode {
  CUPYNUMERIC_BINOP_ADD = 1,
  CUPYNUMERIC_BINOP_ARCTAN2,
  CUPYNUMERIC_BINOP_BITWISE_AND,
  CUPYNUMERIC_BINOP_BITWISE_OR,
  CUPYNUMERIC_BINOP_BITWISE_XOR,
  CUPYNUMERIC_BINOP_COPYSIGN,
  CUPYNUMERIC_BINOP_DIVIDE,
  CUPYNUMERIC_BINOP_EQUAL,
  CUPYNUMERIC_BINOP_FLOAT_POWER,
  CUPYNUMERIC_BINOP_FLOOR_DIVIDE,
  CUPYNUMERIC_BINOP_FMOD,
  CUPYNUMERIC_BINOP_GCD,
  CUPYNUMERIC_BINOP_GREATER,
  CUPYNUMERIC_BINOP_GREATER_EQUAL,
  CUPYNUMERIC_BINOP_HYPOT,
  CUPYNUMERIC_BINOP_ISCLOSE,
  CUPYNUMERIC_BINOP_LCM,
  CUPYNUMERIC_BINOP_LDEXP,
  CUPYNUMERIC_BINOP_LEFT_SHIFT,
  CUPYNUMERIC_BINOP_LESS,
  CUPYNUMERIC_BINOP_LESS_EQUAL,
  CUPYNUMERIC_BINOP_LOGADDEXP,
  CUPYNUMERIC_BINOP_LOGADDEXP2,
  CUPYNUMERIC_BINOP_LOGICAL_AND,
  CUPYNUMERIC_BINOP_LOGICAL_OR,
  CUPYNUMERIC_BINOP_LOGICAL_XOR,
  CUPYNUMERIC_BINOP_MAXIMUM,
  CUPYNUMERIC_BINOP_MINIMUM,
  CUPYNUMERIC_BINOP_MOD,
  CUPYNUMERIC_BINOP_MULTIPLY,
  CUPYNUMERIC_BINOP_NEXTAFTER,
  CUPYNUMERIC_BINOP_NOT_EQUAL,
  CUPYNUMERIC_BINOP_POWER,
  CUPYNUMERIC_BINOP_RIGHT_SHIFT,
  CUPYNUMERIC_BINOP_SUBTRACT,
};

// Match these to WindowOpCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericWindowOpCode {
  CUPYNUMERIC_WINDOW_BARLETT = 1,
  CUPYNUMERIC_WINDOW_BLACKMAN,
  CUPYNUMERIC_WINDOW_HAMMING,
  CUPYNUMERIC_WINDOW_HANNING,
  CUPYNUMERIC_WINDOW_KAISER,
};

// Match these to CuPyNumericRedopCode in config.py
enum CuPyNumericRedopID {
  CUPYNUMERIC_ARGMAX_REDOP = 1,
  CUPYNUMERIC_ARGMIN_REDOP = 2,
};

enum CuPyNumericBounds {
  CUPYNUMERIC_MAX_REDOPS = 1024,
  CUPYNUMERIC_MAX_TASKS  = 1048576,
};

// Match these to ScanCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericScanCode {
  CUPYNUMERIC_SCAN_PROD = 1,
  CUPYNUMERIC_SCAN_SUM,
};

// Match these to ConvertCode in config.py
// Also, sort these alphabetically for easy lookup later
enum CuPyNumericConvertCode {
  CUPYNUMERIC_CONVERT_NAN_NOOP = 1,
  CUPYNUMERIC_CONVERT_NAN_PROD,
  CUPYNUMERIC_CONVERT_NAN_SUM,
};

// Match these to BitGeneratorOperation in config.py
enum CuPyNumericBitGeneratorOperation {
  CUPYNUMERIC_BITGENOP_CREATE       = 1,
  CUPYNUMERIC_BITGENOP_DESTROY      = 2,
  CUPYNUMERIC_BITGENOP_RAND_RAW     = 3,
  CUPYNUMERIC_BITGENOP_DISTRIBUTION = 4,
};

// Match these to BitGeneratorType in config.py
enum CuPyNumericBitGeneratorType {
  CUPYNUMERIC_BITGENTYPE_DEFAULT       = 0,
  CUPYNUMERIC_BITGENTYPE_XORWOW        = 1,
  CUPYNUMERIC_BITGENTYPE_MRG32K3A      = 2,
  CUPYNUMERIC_BITGENTYPE_MTGP32        = 3,
  CUPYNUMERIC_BITGENTYPE_MT19937       = 4,
  CUPYNUMERIC_BITGENTYPE_PHILOX4_32_10 = 5,
};

// Match these to BitGeneratorDistribution in config.py
enum CuPyNumericBitGeneratorDistribution {
  CUPYNUMERIC_BITGENDIST_INTEGERS_16 = 1,
  CUPYNUMERIC_BITGENDIST_INTEGERS_32,
  CUPYNUMERIC_BITGENDIST_INTEGERS_64,
  CUPYNUMERIC_BITGENDIST_UNIFORM_32,
  CUPYNUMERIC_BITGENDIST_UNIFORM_64,
  CUPYNUMERIC_BITGENDIST_LOGNORMAL_32,
  CUPYNUMERIC_BITGENDIST_LOGNORMAL_64,
  CUPYNUMERIC_BITGENDIST_NORMAL_32,
  CUPYNUMERIC_BITGENDIST_NORMAL_64,
  CUPYNUMERIC_BITGENDIST_POISSON,
  CUPYNUMERIC_BITGENDIST_EXPONENTIAL_32,
  CUPYNUMERIC_BITGENDIST_EXPONENTIAL_64,
  CUPYNUMERIC_BITGENDIST_GUMBEL_32,
  CUPYNUMERIC_BITGENDIST_GUMBEL_64,
  CUPYNUMERIC_BITGENDIST_LAPLACE_32,
  CUPYNUMERIC_BITGENDIST_LAPLACE_64,
  CUPYNUMERIC_BITGENDIST_LOGISTIC_32,
  CUPYNUMERIC_BITGENDIST_LOGISTIC_64,
  CUPYNUMERIC_BITGENDIST_PARETO_32,
  CUPYNUMERIC_BITGENDIST_PARETO_64,
  CUPYNUMERIC_BITGENDIST_POWER_32,
  CUPYNUMERIC_BITGENDIST_POWER_64,
  CUPYNUMERIC_BITGENDIST_RAYLEIGH_32,
  CUPYNUMERIC_BITGENDIST_RAYLEIGH_64,
  CUPYNUMERIC_BITGENDIST_CAUCHY_32,
  CUPYNUMERIC_BITGENDIST_CAUCHY_64,
  CUPYNUMERIC_BITGENDIST_TRIANGULAR_32,
  CUPYNUMERIC_BITGENDIST_TRIANGULAR_64,
  CUPYNUMERIC_BITGENDIST_WEIBULL_32,
  CUPYNUMERIC_BITGENDIST_WEIBULL_64,
  CUPYNUMERIC_BITGENDIST_BYTES,
  CUPYNUMERIC_BITGENDIST_BETA_32,
  CUPYNUMERIC_BITGENDIST_BETA_64,
  CUPYNUMERIC_BITGENDIST_F_32,
  CUPYNUMERIC_BITGENDIST_F_64,
  CUPYNUMERIC_BITGENDIST_LOGSERIES,
  CUPYNUMERIC_BITGENDIST_NONCENTRAL_F_32,
  CUPYNUMERIC_BITGENDIST_NONCENTRAL_F_64,
  CUPYNUMERIC_BITGENDIST_CHISQUARE_32,
  CUPYNUMERIC_BITGENDIST_CHISQUARE_64,
  CUPYNUMERIC_BITGENDIST_GAMMA_32,
  CUPYNUMERIC_BITGENDIST_GAMMA_64,
  CUPYNUMERIC_BITGENDIST_STANDARD_T_32,
  CUPYNUMERIC_BITGENDIST_STANDARD_T_64,
  CUPYNUMERIC_BITGENDIST_HYPERGEOMETRIC,
  CUPYNUMERIC_BITGENDIST_VONMISES_32,
  CUPYNUMERIC_BITGENDIST_VONMISES_64,
  CUPYNUMERIC_BITGENDIST_ZIPF,
  CUPYNUMERIC_BITGENDIST_GEOMETRIC,
  CUPYNUMERIC_BITGENDIST_WALD_32,
  CUPYNUMERIC_BITGENDIST_WALD_64,
  CUPYNUMERIC_BITGENDIST_BINOMIAL,
  CUPYNUMERIC_BITGENDIST_NEGATIVE_BINOMIAL,
};

// These fft types match CuPyNumericFFTType in config.py and cufftType
enum CuPyNumericFFTType {
  CUPYNUMERIC_FFT_R2C = 0x2a,  // Real to complex (interleaved)
  CUPYNUMERIC_FFT_C2R = 0x2c,  // Complex (interleaved) to real
  CUPYNUMERIC_FFT_C2C = 0x29,  // Complex to complex (interleaved)
  CUPYNUMERIC_FFT_D2Z = 0x6a,  // Double to double-complex (interleaved)
  CUPYNUMERIC_FFT_Z2D = 0x6c,  // Double-complex (interleaved) to double
  CUPYNUMERIC_FFT_Z2Z = 0x69   // Double-complex to double-complex (interleaved)
};

enum CuPyNumericConvolveMethod {
  CUPYNUMERIC_CONVOLVE_AUTO,
  CUPYNUMERIC_CONVOLVE_DIRECT,
  CUPYNUMERIC_CONVOLVE_FFT,
};

// These fft types match CuPyNumericFFTDirection in config.py and cufftDirection
enum CuPyNumericFFTDirection { CUPYNUMERIC_FFT_FORWARD = -1, CUPYNUMERIC_FFT_INVERSE = 1 };

// Match these to Bitorder in config.py
enum CuPyNumericBitorder { CUPYNUMERIC_BITORDER_BIG = 0, CUPYNUMERIC_BITORDER_LITTLE = 1 };

#ifdef __cplusplus
extern "C" {
#endif

typedef struct ReductionOpIds {
  int argmax_redop_id;
  int argmin_redop_id;
} ReductionOpIds;

void cupynumeric_perform_registration();
bool cupynumeric_has_cusolvermp();

bool cupynumeric_cusolver_has_geev();

unsigned cupynumeric_max_eager_volume();

unsigned cupynumeric_matmul_cache_size();

struct ReductionOpIds cupynumeric_register_reduction_ops(int code);

#ifdef __cplusplus
}
#endif

#endif  // __CUPYNUMERIC_C_H__
